import os
import fiona
import geopandas as gpd
from pathlib import Path


def shp_to_csv_centroid(shp_path, output_csv_path=None):
    """
    将Shapefile转换为CSV，使用质心坐标
    """
    try:
        # 读取Shapefile
        gdf = gpd.read_file(shp_path)

        # 如果地理CRS，转换为投影CRS以获取准确质心
        if gdf.crs and gdf.crs.is_geographic:
            # 使用UTM投影（根据数据位置调整）
            gdf = gdf.to_crs('EPSG:3857')  # Web Mercator

        # 计算质心
        gdf['centroid'] = gdf.geometry.centroid
        gdf['x'] = gdf.centroid.x
        gdf['y'] = gdf.centroid.y

        # 删除几何列和质心列
        csv_df = gdf.drop(columns=['geometry', 'centroid'])

        # 保存
        if output_csv_path is None:
            output_csv_path = shp_path.replace('.shp', '_centroid.csv')

        csv_df.to_csv(output_csv_path, index=False, encoding='utf-8')
        print(f"✓ 成功转换: {shp_path}")
        return True

    except Exception as e:
        print(f"✗ 处理 {os.path.basename(shp_path)} 时出错: {str(e)}")
        return False


def get_gdb_layers(gdb_path):
    """
    获取GDB文件中的所有图层名称

    参数:
    gdb_path: GDB文件或文件夹路径

    返回:
    list: 图层名称列表
    """
    try:
        # 使用fiona获取所有图层
        layers = fiona.listlayers(gdb_path)
        print(f"共读取到{len(layers)}个图层")
        return layers
    except Exception as e:
        print(f"获取GDB图层时出错: {str(e)}")
        return []


def export_gdb_layer_to_csv(gdb_path, layer_name, output_folder, crs_epsg=4490, field_name="OBJNAME"):
    """
    导出GDB中的单个图层为CSV（质心坐标）

    参数:
    gdb_path: GDB文件路径
    layer_name: 图层名称
    output_folder: 输出文件夹
    crs_epsg: 目标投影CRS的EPSG代码（默认4528为中国常用投影）

    返回:
    bool: 成功返回True，失败返回False
    """
    try:
        print(f"正在处理图层: {layer_name}")

        # 读取GDB中的图层
        gdf = gpd.read_file(gdb_path, layer=layer_name)

        if gdf.empty:
            print(f"  警告: 图层 {layer_name} 中没有数据")
            return False

        print(f"读取到 {len(gdf)} 个要素")

        # 检查并处理坐标系
        original_crs = gdf.crs
        print(f"  原始坐标系: {original_crs}")

        # 如果地理CRS，转换为投影CRS以获取准确质心
        if gdf.crs is None:
            print(f"  正在转换到投影坐标系 EPSG:{crs_epsg}")
            try:
                gdf = gdf.to_crs(f'EPSG:{crs_epsg}')
            except Exception as crs_error:
                print(f"  坐标系转换失败: {crs_error}，使用原始坐标系")

        # 计算质心
        # 强制转换为2D几何（去除M值和Z值）
        # gdf['geometry_2d'] = gdf.geometry.apply(lambda geom: geom if geom.is_empty else geom.force_2d())
        print("  计算质心坐标...")
        gdf['centroid'] = gdf.geometry.centroid
        gdf['x'] = gdf.centroid.x
        gdf['y'] = gdf.centroid.y

        # 删除几何列和质心列
        columns_to_drop = ['geometry', 'centroid']
        existing_columns = [col for col in columns_to_drop if col in gdf.columns]
        csv_df = gdf.drop(columns=existing_columns)

        # 保存CSV文件
        # 获取字段，判断字段是否存在
        shp_target_name = ""
        if field_name in gdf.columns:
            shp_target_name = gdf[field_name].iloc[0]
        else:
            print(f"无{field_name}字段，无法对文件进行重命名！")

        if(shp_target_name != ""):
            output_filename = f"{shp_target_name}.csv"
        else:
            output_filename = f"{layer_name}_centroid.csv"
        output_path = os.path.join(output_folder, output_filename)
        csv_df.to_csv(output_path, index=False, encoding='utf-8-sig')

        print(f"  ✓ 成功导出: {output_filename}")
        print(f"    包含 {len(csv_df)} 个要素，{len(csv_df.columns)} 个字段")
        return True

    except Exception as e:
        print(f"  ✗ 处理图层 {layer_name} 时出错: {str(e)}")
        return False


def export_gdb_all_layers(gdb_path, output_folder=None, target_crs=4490):
    """
    导出GDB文件中所有图层为CSV

    参数:
    gdb_path: GDB文件路径
    output_folder: 输出文件夹路径（可选）
    target_crs: 目标投影CRS的EPSG代码
    """
    try:
        # 检查GDB路径是否存在
        if not os.path.exists(gdb_path):
            print(f"错误: GDB路径不存在: {gdb_path}")
            return

        # 设置输出文件夹
        if output_folder is None:
            gdb_name = Path(gdb_path).stem
            output_folder = os.path.join(Path(gdb_path).parent, f"{gdb_name}_export")

        # 创建输出文件夹
        os.makedirs(output_folder, exist_ok=True)

        print(f"GDB文件: {gdb_path}")
        print(f"输出文件夹: {output_folder}")
        print(f"目标坐标系: EPSG:{target_crs}")
        print("-" * 50)

        # 获取所有图层
        layers = get_gdb_layers(gdb_path)

        if not layers:
            print("在GDB中未找到任何图层")
            return

        print(f"找到 {len(layers)} 个图层: {', '.join(layers)}")
        print("-" * 50)

        # 导出每个图层
        success_count = 0
        for layer_name in layers:
            if export_gdb_layer_to_csv(gdb_path, layer_name, output_folder, target_crs):
                success_count += 1
            print("-" * 30)

        print(f"导出完成: 成功 {success_count}/{len(layers)} 个图层")
        print(f"输出位置: {output_folder}")

    except Exception as e:
        print(f"处理GDB文件时出错: {str(e)}")

if __name__ == '__main__':
    input_gdb = r"C:\Users\17673\Downloads\test\部件更新数据库2022_天地图.gdb"
    export_gdb_all_layers(input_gdb, r"E:\data\test", 4490)
    # export_gdb_layer_to_csv(input_gdb, "BJ_0218", r"E:\data\test", 4490)